package Databases;

import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import UserUnit.ImpPhoto;
import java.util.*;
import org.xmldb.api.base.Resource;
import org.xmldb.api.base.ResourceIterator;
import org.xmldb.api.base.ResourceSet;
import org.xmldb.api.base.XMLDBException;
import org.xmldb.api.modules.XMLResource;

public class DatabaseDao implements DbDAO {

    List listresult;
    private static final Log LOG = LogFactory.getLog(DatabaseDao.class);
    protected final String searchbySpecificTag = "search.photos.specifictag";
    protected final String searchbySpecOntologyFLevel = "search.photos.ontology.firstlevel";
    protected final String searchinNewsbyKeyword = "search.innews.photosbykeyword";
    protected final String searchinNewsinparag = "search.innews.paragraphkeyword";
    protected final String searchinNewstitle = "search.innews.phototitlekeyword";
    protected final String searchPhDB = "search.photos.database";
    protected final String searchViDB = "search.videos.database";
    protected final String insertPhotos = "update.insert.photos";
    protected final String deletePhoto = "update.delete.photo";
    protected final String searchIdPhoto = "search.idPhoto";
    protected final String searchbySpecOntologySLevel = "search.pphotos.ontology.secondlevel";

    private DatabaseDao() {
    }

    public List executeQuery(String ActionId, Object[] Parameters) {
        DBManager gestorBD = ImpDBManager.getInstance();
        DBActionResult resultadoBD = gestorBD.execute(new ImpDBAction(ActionId, Parameters));
        if (resultadoBD.isOk()) {
            listresult = resultadoBD.getResult();
        } else {
            LOG.info("Can't execute query due to the error: " + resultadoBD.getErrorMsg() + "and Exception: " + resultadoBD.getException());

        }

        return listresult;
    }

    public void executeInsertQuery(String ActionId, Object[] Parameters) {
        DBManager gestorBD = ImpDBManager.getInstance();
        DBActionResult resultadoBD = gestorBD.execute(new ImpDBAction(ActionId, Parameters));
    }

    /**
     * Queries to use by clients to find pictures.
     *
     */
    public Map seachBySpecificTag(Object[] Parameters) {
        List answer = executeQuery(searchbySpecificTag, Parameters);
        return XmltoJavaObject(answer);
    }

    public Map searchBySpecificOntologyFirstLevel(Object[] Parameters) {
        List answer = executeQuery(searchbySpecOntologyFLevel, Parameters);
        return XmltoJavaObject(answer);
    }

    public Map searchBySpecificOntologySecondLevel(Object[] Parameters) {
        List answer = executeQuery(searchbySpecOntologySLevel, Parameters);
        return XmltoJavaObject(answer);
    }

    public Map searchInNewsByKeyWord(Object[] Parameters) {
        List answer = executeQuery(searchinNewsbyKeyword, Parameters);
        return XmltoJavaObject(answer);
    }

    public Map searchInNewsinParagraph(Object[] Parameters) {
        List answer = executeQuery(searchinNewsinparag, Parameters);
        return XmltoJavaObject(answer);
    }

    public Map searchTitleinNews(Object[] Parameters) {
        List answer = executeQuery(searchinNewstitle, Parameters);
        return XmltoJavaObject(answer);
    }

    public Map searchallPhotos(Object[] Parameters) {
        List answer = executeQuery(searchPhDB, Parameters);
        return XmltoJavaObject(answer);
    }

    /**
     * Query to use by clients to insert/delete pictures.
     *
     */
    public void insertPhoto(ImpPhoto photo) {
        executeInsertQuery(insertPhotos, photoToXml(photo));
    }

    public void deletePhoto(String[] idFile) {
        executeInsertQuery(deletePhoto, idFile);
    }

    /**
     * Query to find the maximum id number of the picture in order to assign the
     * id to the next picture.
     */
    public String searchIdMaxPhoto() throws XMLDBException {
        String id = "0";
        Object[] Parameters = new String[]{""};
        List IdPhoto = executeQuery(searchIdPhoto, Parameters);
        ResourceSet answer = (ResourceSet) IdPhoto.get(0);
        ResourceIterator j;
        j = answer.getIterator();
        while (j.hasMoreResources()) {
            Resource r = j.nextResource();
            id = (String) r.getContent();
        }

        return id;
    }

    /*
     * Parse xml to java object
     */
    public Map XmltoJavaObject(List xmlResource) {
        Map<String, ImpPhoto> photos;
        photos = new HashMap<String, ImpPhoto>();
        ResourceIterator i;
        ResourceSet answer;
        for (int k = 0; k < xmlResource.size(); k++) {
            try {
                answer = (ResourceSet) xmlResource.get(k);
                i = answer.getIterator();
                while (i.hasMoreResources()) {
                    XMLResource xmlr = (XMLResource) i.nextResource();
                    ImpPhoto picture = new ImpPhoto();
                    PhotoHandler setPhoto = new PhotoHandler(picture);
                    xmlr.getContentAsSAX(setPhoto);
                    photos.put(picture.getIdFile(), picture);
                }
            } catch (XMLDBException ex) {
                Logger.getLogger(DatabaseDao.class.getName()).log(Level.SEVERE, null, ex);
            }
        }



        return photos;
    }

    /*
     * ( * Parse xml to java object
     */
    public Object[] photoToXml(ImpPhoto photo) {
        Object[] query;
        String idfile = "1";
        try {
            //aumentamos el id en 1 para añadirselo a la foto
            int idInc = Integer.parseInt(searchIdMaxPhoto());
            idInc = idInc + 1;
            idfile = String.valueOf(idInc);
        } catch (XMLDBException ex) {
            Logger.getLogger(DatabaseDao.class.getName()).log(Level.SEVERE, null, ex);
        }
        List tags = new ArrayList<String>();
        tags = photo.getTags();
        String tag = "";
        for (int i = 0; i < tags.size(); i++) {
            String tempTag = "<tag>" + tags.get(i) + "</tag>";

            tag = tag.concat(tempTag);

        }
        Map<String, String> tax = new HashMap<String, String>();
        String taxValue = "";
        String id = "";
        if (photo.getTaxs() != null) {
            tax = photo.getTaxs();
            List<String> phs = new ArrayList<String>(tax.keySet());
            Collections.sort(phs);
            for (Iterator iterator = phs.iterator(); iterator.hasNext();) {
                id = (String) iterator.next();
                taxValue = tax.get(id);

            }
        }

        query = new String[]{photo.getUserId(), idfile, photo.getFileName(), photo.getFileExtension(), photo.getDay(), photo.getMonth(), photo.getYear(), photo.getHours(), photo.getMinutes(), photo.getWidth(), photo.getHigh(), photo.getSize(), photo.getComment(), photo.getUrl(), tag, id, taxValue};

        return query;
    }

    /*
     * Singleton design pattern
     */
    public static DatabaseDao getInstance() {
        return DaoHolder.INSTANCE;
    }

    public static class DaoHolder {

        private static final DatabaseDao INSTANCE = new DatabaseDao();
    }
}
